package com.hexun.dubbo.overview;

import com.alibaba.dubbo.rpc.protocol.rest.support.ContentType;
import org.jboss.resteasy.core.Dispatcher;
import org.jboss.resteasy.core.ResourceMethodInvoker;
import org.jboss.resteasy.core.ResourceMethodRegistry;
import org.springframework.stereotype.Service;

import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

@Service
@Path("overview")
@Consumes({MediaType.APPLICATION_JSON, MediaType.TEXT_XML})
@Produces({ContentType.APPLICATION_JSON_UTF_8, ContentType.TEXT_XML_UTF_8})
public class ResteasyOverview implements IResteasyOverview {
    List<ResourceDescription> getAvailableEndpoints(@Context Dispatcher dispatcher) {
        ResourceMethodRegistry registry = (ResourceMethodRegistry) dispatcher.getRegistry();
        return ResourceDescription.fromBoundResourceInvokers(registry.getBounded().entrySet());
    }

    @Override
    @GET
    @Produces(MediaType.TEXT_HTML)
    public Response getAvailableEndpointsHtml(@Context Dispatcher dispatcher, @QueryParam("sign") String sign) {
        if (!"hexun8565".equals(sign)) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        List<ResourceDescription> descriptions = getAvailableEndpoints(dispatcher);
        sb.append("<!DOCTYPE html><html>\n");
        sb.append("<head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n<script src=\"https://cdn.bootcss.com/jquery/1.10.1/jquery.min.js\"></script></head><body>\n");
        sb.append("<h1 style='border:solid 1px;'>").append("REST interface 健康检查").append("</h1>\n");
        sb.append("<li>").append("COOKIE  ").append("<input type='text' id='cookie' name='cookie' style='width:100%;height:100px' />").append("</li>\n");
        for (ResourceDescription resource : descriptions) {
            //忽略自身
            if (resource.basePath.contains("overview"))
                continue;
            sb.append("<h2 style='border:solid 1px;'>父路径-->").append(resource.basePath).append("</h2>\n");
            sb.append("<ul>\n");

            for (MethodDescription methodDescription : resource.calls) {
                ResourceMethodInvoker resourceInvoker = (ResourceMethodInvoker) methodDescription.resourceInvoker;
                sb.append("<table style=\"border:solid 1px;width:100%\">")
                        .append("<tr><td style='color:red'> 方法说明</td>")
                        .append("<td style='color: blue'>").append(methodDescription.apiMonitor == null ? "" : methodDescription.apiMonitor.value())
                        .append("</td></tr>")

                        .append("<tr><td>方法</td>")
                        .append("<td style='color: blue'>").append(methodDescription.method)
                        .append("</td></tr>")

                        .append("<tr><td>HttpMethod</td>")
                        .append("<td style='color: blue' class='method'>").append(getHttpMethod(resourceInvoker.getHttpMethods()))
                        .append("</td></tr>")

                        .append("<tr><td>resteasy--路径</td>")
                        .append("<td style='color: blue' class='path'>").append(methodDescription.path)
                        .append("</td></tr>")

                        .append("<tr><td>SAMPLE数据</td>")
                        .append("<td style='color: blue' class='data'>").append("<input type='text' value='" + (methodDescription.apiMonitor == null ? "" : methodDescription.apiMonitor.monitorData()) + "'/>")
                        .append("</td></tr>")

                        .append("<tr><td>正则</td>")
                        .append("<td style='color: blue' class='reg'>").append("<input type='text' value='" + (methodDescription.apiMonitor == null ? "" : methodDescription.apiMonitor.monitorRegex()) + "'/>")
                        .append("</td></tr>")

                        .append("<tr><td>Consumes</td>")
                        .append("<td style='color: blue'>").append(mostPreferredOrNull(resourceInvoker.getConsumes()))
                        .append("</td></tr>")

                        .append("<tr><td>Produces</td>")
                        .append("<td style='color: blue'>").append(mostPreferredOrNull(resourceInvoker.getProduces()))
                        .append("</td></tr>")

                        .append("<tr><td>调用结果</td>")
                        .append("<td style='color: blue'>").append(" <textarea class='result' rows=\"10\" cols=\"200\"></textarea>")
                        .append("</td></tr>")

                        .append("<tr><td><input type='button' value='开始测试' class='checkstart'></td>")
                        .append("<td class='regresult'>").append("")
                        .append("</td></tr>");
                sb.append("</table>");
            }
            sb.append("</ul>\n");
        }
        sb.append("<script type=\"text/javascript\">(function() {\n" +
                "    'use strict';\n" +
                "\n" +
                "    function test(table){\n" +
                "        var path = $(table).find(\".path\").html();\n" +
                "        var method =  $(table).find(\".method\").html();\n" +
                "        var data = $(table).find(\".data\").find(\"input\").val();\n" +
                "        var result = $(table).find(\".result\");\n" +
                "        var regex = $(table).find(\".reg\").find(\"input\").val();\n" +
                "        var checkrst = $(table).find('.regresult');\n" +
                "        var checkinput = $(table).find(\".checkstart\").unbind('click').bind('click',function(){\n" +
                "            test($(table));\n" +
                "        });\n" +
                "        if(data !== ''){\n" +
                "            data = $.parseJSON(data);\n" +
                "            $.each(data,function(key,val){\n" +
                "                if($.isPlainObject(val) || $.isArray(val)){\n" +
                "                    subObj(val);\n" +
                "                }else{\n" +
                "                    path = path.replace('{'+key+'}',val);\n" +
                "                }\n" +
                "            });\n" +
                "        }\n" +
                "        if(path.indexOf('{')>=0){\n" +
                "            return false;\n" +
                "        }\n" +
                "        $.ajax({\n" +
                "            url: path,\n" +
                "            data: data,\n" +
                "            type: method,\n" +
                "            async: false,\n" +
                "            dataType: 'text',\n" +
                "            success: function(data) {\n" +
                "                result.val(data);\n" +
                "                if (regex !== '') {\n" +
                "                    var reg = new RegExp(regex);\n" +
                "                    if (reg.test(data)) {\n" +
                "                        checkrst.attr(\"style\", \"color:green\").html(\"接口返回结果正常。\");\n" +
                "                    } else {\n" +
                "                        checkrst.attr(\"style\", \"color:red\").html(\"接口返回结果异常！\");\n" +
                "                    }\n" +
                "                } else {\n" +
                "                    checkrst.attr(\"style\", \"color:black\").html(\"未检查返回结果！\");\n" +
                "                }\n" +
                "            },\n" +
                "            error: function(XMLHttpRequest, textStatus, errorThrown) {\n" +
                "                console.log(textStatus);\n" +
                "                console.log(errorThrown);\n" +
                "            }\n" +
                "        });\n" +
                "    }\n" +
                "\n" +
                "    function testApi(){\n" +
                "        $('table').each(\n" +
                "            function(){\n" +
                "                test(this);\n" +
                "            }\n" +
                "        );\n" +
                "    }\n" +
                "\n" +
                "\n" +
                "    testApi();\n" +
                "})();" +
                "</script>");

        sb.append("</body></html>");

        return Response.ok(sb.toString()).build();
    }


    /**
     * print media type
     *
     * @param mediaTypes
     * @return
     */
    private static String mostPreferredOrNull(MediaType[] mediaTypes) {
        if (mediaTypes == null || mediaTypes.length < 1) {
            return null;
        } else {
            StringBuilder builder = new StringBuilder();
            for (MediaType mediaType : mediaTypes) {
                builder.append(mediaType.toString()).append(" | ");
            }
            builder.delete(builder.length() - 2, builder.length() - 1);
            return builder.toString();
        }
    }

    /**
     * 聚合 http method
     *
     * @param httpMethods
     * @return
     */
    private static String getHttpMethod(Set<String> httpMethods) {
        StringBuilder builder = new StringBuilder();
        Iterator<String> iterator = httpMethods.iterator();
        while (iterator.hasNext()) {
            builder.append(iterator.next() + ",");
        }
        builder.delete(builder.length() - 1, builder.length());
        return builder.toString();
    }
}
